#include "PWaveStencilMath.h"

#ifdef USE_SW_ATHREAD

#ifdef USE_MASTER_ONLY

#define STENCIL_4_KERN stencil_order_4_kern
#define STENCIL_4_PML_KERN stencil_order_4_pml_kern

#else // not USE_MASTER_ONLY

#define STENCIL_4_KERN slave_stencil_order_4_kern_athread
#define STENCIL_4_PML_KERN slave_stencil_order_4_pml_kern_athread

#endif // USE_MASTER_ONLY

#elif defined(USE_SW_ACC)

#define STENCIL_4_KERN stencil_order_4_kern_acc
#define STENCIL_4_PML_KERN stencil_order_4_pml_kern_acc

#else // USE_INTEL_COMPILER or USE_GNU_COMPILER

#define STENCIL_4_KERN stencil_order_4_kern
#define STENCIL_4_PML_KERN stencil_order_4_pml_kern

#endif // USE_SW_ATHREAD, USE_SW_ACC



void PWaveStencilMath::stencil_order_4_pml_core(double* dst, const double* src, const double* coeffc2_dist, const double* c2dtQ_dist,
                                         int halo, int ldx, int ldy, int ldz,
                                         int non_pml_min_x, int non_pml_max_x) {
    if(halo < non_pml_min_x) {
#ifdef __DEBUG__
        printf("#1 circum\n");
#endif
        STENCIL_4_PML_KERN(dst, src, coeffc2_dist, c2dtQ_dist, halo, 2 * halo, 2 * halo,
                           non_pml_min_x, ldy - 2 * halo, ldz - 2 * halo, ldx, ldy);
    }

    if(non_pml_min_x < non_pml_max_x) {
#ifdef __DEBUG__
        printf("#2 circum\n");
#endif
        STENCIL_4_KERN(dst, src, coeffc2_dist, non_pml_min_x, 2 * halo, 2 * halo,
                       non_pml_max_x, ldy - 2 * halo, ldz - 2 * halo, ldx, ldy);
    }

    if(non_pml_max_x < ldx - halo) {
#ifdef __DEBUG__
        printf("#3 circum\n");
#endif
        STENCIL_4_PML_KERN(dst, src, coeffc2_dist, c2dtQ_dist, non_pml_max_x, 2 * halo, 2 * halo,
                           ldx - halo, ldy - 2 * halo, ldz - 2 * halo, ldx, ldy);
    }
}


void PWaveStencilMath::stencil_order_4_pml_corner(double* dst, const double* src, const double* coeffc2_dist, const double* c2dtQ_dist,
                                           int halo, int ldx, int ldy, int ldz) {
    // -y, -z corner
    stencil_order_4_pml_kern(dst, src, coeffc2_dist, c2dtQ_dist,
                             halo, halo, halo,
                             ldx - halo, 2 * halo, 2 * halo, ldx, ldy);

    // -y, +z corner
    stencil_order_4_pml_kern(dst, src, coeffc2_dist, c2dtQ_dist,
                             halo, halo, ldz - 2 * halo,
                             ldx - halo, 2 * halo, ldz - halo, ldx, ldy);

    // +y, -z corner
    stencil_order_4_pml_kern(dst, src, coeffc2_dist, c2dtQ_dist,
                             halo, ldy - 2 * halo, halo,
                             ldx - halo, ldy - halo, 2 * halo, ldx, ldy);

    // +y, +z corner
    stencil_order_4_pml_kern(dst, src, coeffc2_dist, c2dtQ_dist,
                             halo, ldy - 2 * halo, ldz - 2 * halo,
                             ldx - halo, ldy - halo, ldz - halo, ldx, ldy);
}


void PWaveStencilMath::compute_wave_src(double* dst, const std::vector<LocalSrcInfo>& local_src_info, double t) {
    // dst[loc] = Ricker(f, t, 0);
    for(int i = 0; i < local_src_info.size(); i++)
        dst[local_src_info[i].inblk_src_loc] = local_src_info[i].amp * Ricker(local_src_info[i].f, t, local_src_info[i].t0);

}
